package zunge.lbe1;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

/**
 * Flow2: Direct Classification
 * 	Method1: p -> d
 * 	Method2: a,p -> d
 * 	Method3: u,a,p -> d
 */
public class Flow2 {
	List<DataFold> dataFolds;
	
	public Flow2(List<DataFold> dataFolds){
		this.dataFolds = dataFolds;
	}

	//label: train, test, model, out, log
	public static String getMFile(int v, String tmpFolder, int method,String label){
		return tmpFolder+v+"_m"+method+"_"+label+".txt";
	}
	
	
	public static String getMResultFile(String resultFolder, int method){
		return resultFolder+"m"+method+".txt";
	}
	
	/**
	 * Generate input,output in temp/
	 * Generate script in script/
	 * return the command to run the script
	 * @throws IOException 
	 */
	public void generate(ScriptGen sg) throws IOException{
		List<String> scripts = new ArrayList<String>();
		
		for(DataFold dataFold:dataFolds){
			genM(1, dataFold, scripts, sg);
			genM(2, dataFold, scripts, sg);
			genM(3, dataFold, scripts, sg);
		}
		
		String scriptDir = dataFolds.get(0).data.getScriptDir();
		String tempDir = dataFolds.get(0).data.getTempDir();
		
		sg.splitScript(scripts, Data.CORES, "flow2", "flow2.sh", 
				scriptDir, tempDir);
	}
	void genM(int method, DataFold dataFold, List<String> scripts, ScriptGen sg) throws IOException{
		String tmpFolder = dataFold.data.getTempDir();
		String f_train = getMFile(dataFold.v, tmpFolder, method, "train");
		String f_test = getMFile(dataFold.v, tmpFolder, method, "test");
		String f_model = getMFile(dataFold.v, tmpFolder, method, "model");
		String f_output = getMFile(dataFold.v, tmpFolder, method, "out");
		String f_log = getMFile(dataFold.v, tmpFolder, method, "log");
		
		//Remove previous results
		new File(f_model).delete();
		new File(f_output).delete();
		new File(f_log).delete();
		
		genFile(method, dataFold.data, dataFold.getTrainSetFile(), f_train);
		genFile(method, dataFold.data, dataFold.getTestSetFile(), f_test);
		
		scripts.add(sg.genLibLinear(f_train, f_test, f_model, f_output, f_log));
	}
	void genFile(int method, Data data, String inputFile, String outputFile) throws IOException{
		BufferedReader br = new BufferedReader(new FileReader(inputFile));
		BufferedWriter bw = new BufferedWriter(new FileWriter(outputFile));
		String line;
		int uid,aid,pid,did;
		while((line=br.readLine())!=null){
			String[] frags = line.split(" ");
			did = Integer.parseInt(frags[3]);
			if(did==0){continue;}
			
			uid = Integer.parseInt(frags[0]);
			aid = Integer.parseInt(frags[1]);
			pid = Integer.parseInt(frags[2]);
			switch(method){
			case 1://Method1: p -> d
				bw.write(did+" "+pid+":1\n");
				break;
			case 2://Method2: a,p -> d
				bw.write(did+" "+pid+":1 "+(aid+data.P)+":1\n");
				break;
			case 3://Method3: u,a,p - > d
				bw.write(did+" "+pid+":1 "+(aid+data.P)+":1 "+(uid+data.aMap.size()+data.P)+":1\n");
				break;
			default:		
			}
		}
		br.close();
		bw.close();
	}
	
	public void run(String cmd, String tmpFolder,String label) throws IOException, InterruptedException{
		System.out.println("\texec script:\n\t\t"+cmd);
		
		Process p = Runtime.getRuntime().exec(cmd);
		p.waitFor();
		System.out.println("\tscript running");
		BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
		String line;
		while ((line=reader.readLine())!=null){System.out.println("\t\t"+line);}
		
		ScriptGen.SignalObserver so = new ScriptGen.SignalObserver(
				tmpFolder, label, Data.CORES, false);
		
		so.waitWhenFinish();
		System.out.println("\tsignalobserver finished");
	}
	
	public void collectResult() throws IOException{
		collectM(1, getMResultFile(dataFolds.get(0).data.getResultDir(),1));
		collectM(2, getMResultFile(dataFolds.get(0).data.getResultDir(),2));
		collectM(3, getMResultFile(dataFolds.get(0).data.getResultDir(),3));
	}
	void collectM(int method, String resultFile) throws IOException{
		double totalAcc = 0;
		BufferedWriter bw = new BufferedWriter(new FileWriter(resultFile));
		for(DataFold dataFold:dataFolds){
			String logFile = getMFile(dataFold.v, dataFold.data.getTempDir(), method, "log");
			BufferedReader br = new BufferedReader(new FileReader(logFile));
			String line = br.readLine();
			double acc = Double.parseDouble(line.substring(line.indexOf('=')+1, line.indexOf('%')));
			bw.write(acc+"\t");
			totalAcc += acc;
			br.close();
		}
		bw.write("\n"+totalAcc/dataFolds.size()+"\n");
		bw.close();
	}
	
	
	/** input: record
	 * output: string with ids of each field 
	 * @throws IOException */
	public static String translateFeatures(Data data, String record, int method) throws IOException{
		String[] frags = record.split(" ");
		switch(method){
		case 1://Method1: p -> d
			return frags[0]+" "+Integer.parseInt(frags[1].substring(0,frags[1].indexOf(":")));
		case 2://Method2: a,p -> d
			return frags[0]
					+" "+Integer.parseInt(frags[1].substring(0,frags[1].indexOf(":")))
					+" "+(Integer.parseInt(frags[2].substring(0,frags[2].indexOf(":"))) - Data.P) ;
		case 3://Method3: u,a,p - > d
			return frags[0]
					+" "+Integer.parseInt(frags[1].substring(0,frags[1].indexOf(":")))
					+" "+(Integer.parseInt(frags[2].substring(0,frags[2].indexOf(":"))) - Data.P) 
					+" "+(Integer.parseInt(frags[3].substring(0,frags[3].indexOf(":"))) - Data.P - data.aMap.size()) ;
		default:
			throw new IOException("wrong method");
		}
	}
}
